package com.addplus.townmall.server.web.provider.utils;

import com.addplus.townmall.server.api.model.base.BaseModel;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * 类名：
 *
 * @author fuyongqiang
 * @version V1.0
 * @date 2018/01/19 14:06
 * @description 描述：
 */
public class ExcelUtils<T> {

    /**
     * 描述：这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
     *
     * @param title    表格标题名
     * @param headers  表格属性列名数组
     * @param dataList 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
     * @param out      与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
     * @author fuyongqiang
     * @date 2018-01-19 14:12:53
     */
    public void exportExcel(String title, List<ExcelHeader> headers, Collection<T> dataList, OutputStream out) {
        // 声明一个工作薄
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        try {
            // 生成一个表格
            SXSSFSheet sheet = workbook.createSheet(title);
            // 设置表格默认列宽度为15个字节
            sheet.setDefaultColumnWidth((short) 15);
            CellStyle style = workbook.createCellStyle();
//        style.setAlignment();

            // 产生表格标题行
            SXSSFRow row = sheet.createRow(0);
            Collections.sort(headers);
            for (short i = 0; i < headers.size(); i++) {
                SXSSFCell cell = row.createCell(i);
                cell.setCellStyle(style);
                cell.setCellValue(headers.get(i).getTitle());
            }
            Iterator<T> iterator = dataList.iterator();
            int index = 0;
            Method method = null;
            // 遍历集合数据，产生数据行
            while (iterator.hasNext()) {
                index++;
                row = sheet.createRow(index);
                T t = iterator.next();
                // 根据头取出需要生成数据
                for (short j = 0; j < headers.size(); j++) {
                    SXSSFCell cell = row.createCell(j);
                    Class tClass = t.getClass();
                    try {
                        method = tClass.getMethod(getMethodName(headers.get(j).getFieldName()), new Class[]{});
                    } catch (NoSuchMethodException e) {
                        method = BaseModel.class.getMethod(getMethodName(headers.get(j).getFieldName()), new Class[]{});
                    }
                    Object value = method.invoke(t);
                    if (headers.get(j).getCallBack() != null) {
                        value = headers.get(j).getCallBack().call(value);
                    }
                    if (value instanceof Integer) {
                        cell.setCellValue((Integer) value);
                    } else if (value instanceof Float) {
                        cell.setCellValue((Float) value);
                    } else if (value instanceof Double) {
                        cell.setCellValue((Double) value);
                    } else if (value instanceof BigDecimal) {
                        cell.setCellValue(((BigDecimal) value).doubleValue());
                    } else if (value instanceof Long) {
                        cell.setCellValue((Long) value);
                    } else {
                        if (value == null) {
                            value = "";
                        }
                        cell.setCellValue(value.toString());
                    }
                }
            }
            // 写入流
            workbook.write(out);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getMethodName(String fieldName) {
        return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }
}

